
/*
This file contains the declarations of a number of procedures to generate
random type graph either for families of instances or stand-alone graphs.

Copyright (C) 2018  Denis Pankratov

Modifications Copyright (C) 2019 Christodoulos Karavasilis

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once

#include "bmcommon.h"
#include "graph.h"
#include <cstdlib>
#include <set>
#include <random>
using namespace std;


/*
Generates a sample of the binomial random variable with parameters n and p 
in expected time O(np).
Uses second waiting moment from page 552 Devroye's book
*/
int getBinomial(int n, double p);

/*
Generates a sample of the binomial random variable with parameters n and p 
in time O(n).
Uses the trivial algorithm.
*/
int getBinomialSlow(int n, double p);

/*
Generate k uniform random numbers between 0 and n
*/
set<int> generateRandomNeighbors(int n, int k);

/*
Returns a bipartite Erdos-Renyi graph where 

n - number of online nodes
m - number of online nodes
p - probability that an edge (i,j) is generated
*/
Graph bipartiteErdosRenyi(int n, int m, double p);

/*
Returns a random graph that is d-regular on the left or d-regular on the right.
The graph has n nodes on the left, m on the right.
We assume that d is much less than n.
*/
Graph generateDRegular(int n, int m, int d, bool leftRegular);


/*
Generates a triangular graph that is the worst case graph for
RANKING (see KVV paper), where n is the number of online nodes.
*/
Graph triangular(int n);

/*
Generate hexa type graph.
*/
Graph hexa(int b);

/*
Create a worst case Feldman et al.
n should be a multiple of 4!
*/
Graph worstCaseFeldman(int n);

/*
Generate rope graph from Augment or Push paper
with k blocks of size d each
*/
Graph rope(int k, int d);

/*Creates a zipf graph from Augment or Push paper*/
Graph zipf(int n, int d);

/*
Fewg and manyg graphs from Augment or Push paper with 
g groups of size sz each.
*/
Graph fewgAndManyg(int g, int sz, int d);

/*
Returns ManshadiEtAl graph that is current leader of worst-case graphs
for all integral known i.i.d. graphs.
*/
Graph manshadiWorstCase(int n);


/*
Returns a complete bipartite graph with n online nodes and m offline nodes.
*/
Graph bipartiteComplete(int n, int m);


/*
Samples a number between 0 and cdf.size()-1 (inclusive) where number i appears
with probability
cdf[i]-cdf[i-1], where cdf[-1] = 0.0. The cdf vector must satisfy that
cdf[i] >= cdf[i-1] and cdf[cdf.size()-1] = 1.0.
cdf must have size  > 0.
*/
int sampleFromCDF(const vector<double> &cdf);

/*
Create preferential attachment bigraph
*/
Graph preferentialAttachmentBiGraph(int n, double c);


/*
Returns a vector of length m, where each entry is a random number
between 0 and n.
*/
vector<int> iid(int n, int m);



/*
Generates the CDF for the power law distribution with the given exponent and 
cutoff.
Goes until the increments in cdf become super small. Thus, has finite support.
*/
vector<double> powerLawCDF(double exponent, double cutoff);


/*
Given a CDF for the degree distribution, constrcut a graph on n nodes using 
Molloy-Reed construction.
If randomBipartition is set to true, the graph returned is obtained by first 
doing the above construction, then partitioning nodes randomly into two
balanced sets and keeping the edges only between sets.
*/
Graph generateMolloyReed(int n, const vector<double> & degCDF,
	bool randomBipartition);